package com.zzw.basic.io.aio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AIOServer2 {

    private final static int port = 30000;
    private final static String UTF_8 = "utf-8";
    private static Map<AsynchronousSocketChannel,String> users = new HashMap<>();
    private static List<AsynchronousSocketChannel> channelList = new ArrayList<>();

    public void startListen() throws Exception {
        ExecutorService exector = Executors.newFixedThreadPool(20);
        AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(exector);
        AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open(group).bind(new InetSocketAddress(port));
        serverSocketChannel.accept(null,new AcceptHandler(serverSocketChannel));
        Thread.sleep(10000);
    }

    public static void main(String[] args) throws Exception {
        AIOServer2 server = new AIOServer2();
        server.startListen();
        System.out.println("*************");
    }

    private class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel,Object>{

        private AsynchronousServerSocketChannel serverSocketChannel;
        private ByteBuffer buff = ByteBuffer.allocate(1024);
        
        public AcceptHandler(AsynchronousServerSocketChannel channel){
            this.serverSocketChannel = channel;
        }
        
        @Override
        public void completed(AsynchronousSocketChannel sc, Object attachment) {
            System.out.println("completed1");
            //AIOServer2.channelList.add(sc);
            AIOServer2.users.put(sc,"");
            serverSocketChannel.accept(null,this);
            sc.read(buff, null, new CompletionHandler<Integer, Object>() {

                @Override
                public void completed(Integer result, Object attachment) {
                    System.out.println("completed2");
                    buff.flip();
                    String content = StandardCharsets.UTF_8.decode(buff).toString();
                    String contents[] = content.split(",");
                    if(contents.length == 2) {
                        String name = contents[0];
                        String msg = contents[1];
                        for (Map.Entry<AsynchronousSocketChannel,String > entry:users.entrySet()){
                            if (entry.getValue().equals(name)){
                                try {
                                    entry.getKey().write(ByteBuffer.wrap(msg.getBytes(AIOServer2.UTF_8))).get();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                    else users.put(sc,contents[0]);//注册名字

                    /*for (AsynchronousSocketChannel c:AIOServer2.channelList){
                        try {
                            c.write(ByteBuffer.wrap(content.getBytes(AIOServer2.UTF_8))).get();
                        } catch (Exception e) {
                            channelList.remove(c);
                            e.printStackTrace();
                        }
                    }*/
                    buff.clear();
                    sc.read(buff, null, this);
                }

                @Override
                public void failed(Throwable exc, Object attachment) {
                    System.out.println("读取数据失败:" + exc);
                    AIOServer2.channelList.remove(sc);
                }
            });
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            System.out.println("连接失败:" + exc);
        }
    }
}
